#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <vector>
#include <string>

/**
 * @brief 测试统计结构
 */
struct TestStats {
    int total = 0;
    int passed = 0;
    int failed = 0;
};

static TestStats g_stats;

/**
 * @brief 错误处理函数
 * @param msg 错误消息
 */
static void die(const char *msg) {
    int err = errno;
    fprintf(stderr, "[%d] %s\n", err, msg);
    abort();
}

/**
 * @brief 从缓冲区读取32位整数
 * @param buf 缓冲区
 * @return 32位整数
 */
static uint32_t read_le32(const uint8_t *buf) {
    uint32_t val = 0;
    memcpy(&val, buf, 4);
    return val;
}

/**
 * @brief 向缓冲区写入32位整数
 * @param buf 缓冲区
 * @param val 32位整数
 */
static void write_le32(uint8_t *buf, uint32_t val) {
    memcpy(buf, &val, 4);
}

/**
 * @brief 从缓冲区读取64位整数
 * @param buf 缓冲区
 * @return 64位整数
 */
static uint64_t read_le64(const uint8_t *buf) {
    uint64_t val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 从缓冲区读取双精度浮点数
 * @param buf 缓冲区
 * @return 双精度浮点数
 */
static double read_dbl(const uint8_t *buf) {
    double val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 序列化类型
 */
enum {
    SER_NIL = 0,    // 空值
    SER_ERR = 1,    // 错误码 + 消息
    SER_STR = 2,    // 字符串
    SER_INT = 3,    // int64
    SER_DBL = 4,    // double
    SER_ARR = 5,    // 数组
};

/**
 * @brief 解析响应数据
 * @param data 响应数据
 * @param len 数据长度
 * @param pos 当前位置（引用）
 * @return 解析成功返回0
 */
static int32_t parse_response(const uint8_t *data, uint32_t len, uint32_t &pos) {
    if (pos >= len) {
        printf("(nil)\n");
        return 0;
    }
    
    uint8_t type = data[pos++];
    switch (type) {
    case SER_NIL:
        printf("(nil)");
        break;
    case SER_ERR:
        if (pos + 4 > len) return -1;
        {
            int32_t code = 0;
            memcpy(&code, &data[pos], 4);
            pos += 4;
            if (pos + 4 > len) return -1;
            uint32_t msg_len = read_le32(&data[pos]);
            pos += 4;
            if (pos + msg_len > len) return -1;
            printf("(err) %d %.*s", code, msg_len, &data[pos]);
            pos += msg_len;
        }
        break;
    case SER_STR:
        if (pos + 4 > len) return -1;
        {
            uint32_t str_len = read_le32(&data[pos]);
            pos += 4;
            if (pos + str_len > len) return -1;
            printf("\"%.*s\"", str_len, &data[pos]);
            pos += str_len;
        }
        break;
    case SER_INT:
        if (pos + 8 > len) return -1;
        {
            int64_t val = (int64_t)read_le64(&data[pos]);
            pos += 8;
            printf("(int) %lld", (long long)val);
        }
        break;
    case SER_DBL:
        if (pos + 8 > len) return -1;
        {
            double val = read_dbl(&data[pos]);
            pos += 8;
            printf("(dbl) %g", val);
        }
        break;
    case SER_ARR:
        if (pos + 4 > len) return -1;
        {
            uint32_t arr_len = read_le32(&data[pos]);
            pos += 4;
            printf("(arr) len=%u", arr_len);
            for (uint32_t i = 0; i < arr_len; ++i) {
                printf("\n  [%u] ", i);
                if (parse_response(data, len, pos) != 0) {
                    return -1;
                }
            }
        }
        break;
    default:
        printf("Unknown response type: %u", type);
        return -1;
    }
    return 0;
}

/**
 * @brief 发送请求
 * @param fd 套接字
 * @param cmd 命令参数
 * @return 发送成功返回0
 */
static int32_t send_req(int fd, const std::vector<std::string> &cmd) {
    uint32_t len = 4;
    for (const std::string &s : cmd) {
        len += 4 + s.size();
    }
    if (len > 4096) {
        return -1;
    }

    char wbuf[4 + 4096];
    write_le32((uint8_t *)&wbuf[0], len);
    write_le32((uint8_t *)&wbuf[4], cmd.size());
    size_t cur = 8;
    for (const std::string &s : cmd) {
        write_le32((uint8_t *)&wbuf[cur], s.size());
        memcpy(&wbuf[cur + 4], s.data(), s.size());
        cur += 4 + s.size();
    }

    uint32_t total_len = len + 4;
    return write(fd, wbuf, total_len) == (ssize_t)total_len ? 0 : -1;
}

/**
 * @brief 读取响应
 * @param fd 套接字
 * @return 读取成功返回0
 */
static int32_t read_res(int fd) {
    // 读取4字节长度
    char rbuf[4 + 4096 + 1];
    errno = 0;
    int32_t err = read(fd, rbuf, 4);
    if (err != 4) {
        if (err < 0) {
            perror("read");
        } else {
            fprintf(stderr, "EOF\n");
        }
        return -1;
    }

    uint32_t len = read_le32((uint8_t *)rbuf);
    if (len > 4096) {
        fprintf(stderr, "too long\n");
        return -1;
    }

    // 读取响应体
    err = read(fd, &rbuf[4], len);
    if (err != (int32_t)len) {
        if (err < 0) {
            perror("read");
        } else {
            fprintf(stderr, "EOF\n");
        }
        return -1;
    }

    // 解析响应
    uint32_t pos = 0;
    return parse_response((uint8_t *)&rbuf[4], len, pos);
}

/**
 * @brief 执行单个测试
 * @param fd 文件描述符
 * @param test_name 测试名称
 * @param cmd 命令
 * @param expected_output 期望输出（可选）
 */
static void run_test(int fd, const char* test_name, const std::vector<std::string> &cmd, const char* expected_output = nullptr) {
    g_stats.total++;
    printf("\n🧪 测试: %s\n", test_name);
    printf("📤 命令: ");
    for (size_t i = 0; i < cmd.size(); i++) {
        printf("%s%s", i > 0 ? " " : "", cmd[i].c_str());
    }
    printf("\n📥 响应: ");
    
    int32_t err = send_req(fd, cmd);
    if (err) {
        printf("❌ 发送失败\n");
        g_stats.failed++;
        return;
    }
    
    err = read_res(fd);
    if (err) {
        printf("❌ 读取响应失败\n");
        g_stats.failed++;
        return;
    }
    
    if (expected_output) {
        printf("\n✅ 期望: %s", expected_output);
    }
    printf("\n✅ 测试通过\n");
    g_stats.passed++;
}

/**
 * @brief 打印测试分组标题
 */
static void print_section(const char* title) {
    printf("\n" "=" "===============================================\n");
    printf("📋 %s\n", title);
    printf("===============================================\n");
}

/**
 * @brief 主函数
 */
int main(int argc, char **argv) {
    (void)argc; (void)argv; // 避免未使用参数警告
    
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        die("socket()");
    }

    struct sockaddr_in addr = {};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(1234);
    addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);  // 127.0.0.1
    int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr));
    if (rv) {
        die("connect");
    }

    printf("🚀 Redis服务器全面功能测试开始...\n");
    printf("🔗 已连接到服务器 127.0.0.1:1234\n");

    // 1. 基本字符串操作测试
    print_section("基本字符串操作测试");
    run_test(fd, "设置键值对", {"set", "name", "Alice"});
    run_test(fd, "获取存在的键", {"get", "name"});
    run_test(fd, "获取不存在的键", {"get", "nonexistent"});
    run_test(fd, "覆盖现有键", {"set", "name", "Bob"});
    run_test(fd, "验证键值更新", {"get", "name"});

    // 2. 中文字符支持测试
    print_section("中文字符支持测试");
    run_test(fd, "设置中文键值", {"set", "姓名", "张三"});
    run_test(fd, "获取中文键值", {"get", "姓名"});
    run_test(fd, "设置混合字符", {"set", "用户信息", "姓名:李四,年龄:25,城市:北京"});
    run_test(fd, "获取混合字符", {"get", "用户信息"});

    // 3. 特殊字符和边界条件测试
    print_section("特殊字符和边界条件测试");
    run_test(fd, "空字符串值", {"set", "empty", ""});
    run_test(fd, "获取空字符串", {"get", "empty"});
    run_test(fd, "包含空格的值", {"set", "space_key", "hello world with spaces"});
    run_test(fd, "特殊符号", {"set", "symbols", "!@#$%^&*()_+-=[]{}|;:'\",.<>?/`~"});
    run_test(fd, "数字字符串", {"set", "number_str", "123456789"});

    // 4. 键管理和列举测试
    print_section("键管理测试");
    run_test(fd, "列出所有键", {"keys"});
    run_test(fd, "删除存在的键", {"del", "name"});
    run_test(fd, "删除不存在的键", {"del", "nonexistent_key"});
    run_test(fd, "删除后验证", {"get", "name"});
    run_test(fd, "删除后列出键", {"keys"});

    // 5. 有序集合基础测试
    print_section("有序集合基础测试");
    run_test(fd, "创建有序集合", {"zadd", "scores", "95.5", "数学"});
    run_test(fd, "添加更多成员", {"zadd", "scores", "87.0", "英语"});
    run_test(fd, "添加第三个成员", {"zadd", "scores", "92.5", "语文"});
    run_test(fd, "获取成员分数", {"zscore", "scores", "数学"});
    run_test(fd, "获取不存在成员分数", {"zscore", "scores", "物理"});

    // 6. 有序集合高级测试
    print_section("有序集合高级测试");
    run_test(fd, "范围查询(全部)", {"zquery", "scores", "0", "", "0", "10"});
    run_test(fd, "范围查询(限制数量)", {"zquery", "scores", "0", "", "0", "2"});
    run_test(fd, "范围查询(偏移)", {"zquery", "scores", "0", "", "1", "2"});
    run_test(fd, "更新现有成员分数", {"zadd", "scores", "96.0", "数学"});
    run_test(fd, "验证分数更新", {"zscore", "scores", "数学"});
    run_test(fd, "删除集合成员", {"zrem", "scores", "英语"});
    run_test(fd, "删除不存在成员", {"zrem", "scores", "物理"});
    run_test(fd, "删除后查询", {"zquery", "scores", "0", "", "0", "10"});

    // 7. TTL过期时间测试
    print_section("TTL过期时间测试");
    run_test(fd, "设置临时键", {"set", "temp_key", "临时数据"});
    run_test(fd, "设置过期时间(5秒)", {"pexpire", "temp_key", "5000"});
    run_test(fd, "查询TTL", {"pttl", "temp_key"});
    run_test(fd, "不存在键的TTL", {"pttl", "nonexistent"});
    run_test(fd, "永久键的TTL", {"pttl", "姓名"});
    run_test(fd, "设置过期时间(1秒)", {"pexpire", "temp_key", "1000"});
    
    printf("\n⏳ 等待1.5秒让键过期...\n");
    usleep(1500000); // 等待1.5秒
    
    run_test(fd, "查询过期键", {"get", "temp_key"});
    run_test(fd, "过期键的TTL", {"pttl", "temp_key"});

    // 8. 错误处理测试
    print_section("错误处理测试");
    run_test(fd, "无效命令", {"invalid_command"});
    run_test(fd, "参数不足", {"set", "key_only"});
    run_test(fd, "有序集合类型错误", {"zadd", "姓名", "invalid_score", "member"});
    run_test(fd, "字符串操作有序集合", {"get", "scores"});

    // 9. 混合数据类型测试
    print_section("混合数据类型测试");
    run_test(fd, "设置多种类型键", {"set", "user:1:name", "用户1"});
    run_test(fd, "创建用户分数集合", {"zadd", "user:1:scores", "85.5", "期中考试"});
    run_test(fd, "添加更多分数", {"zadd", "user:1:scores", "92.0", "期末考试"});
    run_test(fd, "查看所有键", {"keys"});
    
    // 10. 大数据量测试
    print_section("批量数据测试");
    for (int i = 1; i <= 5; i++) {
        std::string key = "batch_key_" + std::to_string(i);
        std::string value = "批量数据_" + std::to_string(i);
        run_test(fd, ("批量设置键" + std::to_string(i)).c_str(), {"set", key, value});
    }
    
    for (int i = 1; i <= 10; i++) {
        std::string member = "成员_" + std::to_string(i);
        std::string score = std::to_string(i * 10.5);
        run_test(fd, ("批量添加有序集合" + std::to_string(i)).c_str(), 
                {"zadd", "large_zset", score, member});
    }
    
    run_test(fd, "查询大有序集合", {"zquery", "large_zset", "0", "", "0", "20"});
    run_test(fd, "最终键列表", {"keys"});

    // 测试总结
    printf("\n" "=" "===============================================\n");
    printf("📊 测试完成统计\n");
    printf("===============================================\n");
    printf("✅ 总测试数: %d\n", g_stats.total);
    printf("✅ 通过测试: %d\n", g_stats.passed);
    printf("❌ 失败测试: %d\n", g_stats.failed);
    printf("📈 成功率: %.1f%%\n", 
           g_stats.total > 0 ? (100.0 * g_stats.passed / g_stats.total) : 0.0);
    
    if (g_stats.failed == 0) {
        printf("\n🎉 所有测试通过！Redis服务器功能完整可用！\n");
    } else {
        printf("\n⚠️  有 %d 个测试失败，请检查服务器实现\n", g_stats.failed);
    }
    
    printf("\n🔌 断开连接...\n");
    close(fd);
    return g_stats.failed > 0 ? 1 : 0;
} 